package com.dingding.javabasic.集合;

import com.alibaba.fastjson.JSON;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class Solution {


    /**
     * 集合转数组
     */
    @Test
    public void test1() {
        String[] s = new String[]{"dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A"};
        List<String> list = Arrays.asList(s);
//        s= (String[]) list.toArray();
//
//        Object[] a = new String[]{"dog"};
//
//        Object b = new String[]{"12"};
//        String[] x = (String[]) b;
//
        List<Integer> integerList = new ArrayList<>(10);
        integerList.add(2);
        integerList.add(2, 2);
//        Set<String> set = new HashSet<>(null);
    }

    @Test
    public void test2() {
        HashMap<String, String> map = new HashMap<>();
        map.put("1","1");
        map.put("1","1");
        map.get("1");
    }

    /**
     * 测试hashmap形成链表的过程
     */
    @Test
    public void test3(){
        //好处1：这里为什么定义2的n次幂作为数组的长度，因为在确定数组下标的时候，(tab.length - 1)转化为二进制就是1111，这样高位就一定是0，低4位在做&运算的时候会增加散列程度
        //好处2：(tab.length - 1) & key.hashCode 的时候，数组下标最大的情况也就是15，绝对不会出现数组越界的情况
        List<String> list = Lists.newArrayList(
                "张三","李四","王五","赵六","孙七","钱八","刘九","刘功顶"
                ,"张1z三","李2x四","王3c五","赵4v六","孙5b七","钱6n八","刘7m九","刘8,功顶"
        );
        String[] tab = new String[list.size()];
        for (String key : list) {
            int index = key.hashCode() & (tab.length - 1);
            System.out.printf("key值=%s index=%d%n", key, index);
            //这里并不是顺序赋值，但绝不会数组越界
            if (tab[index] == null) {
                tab[index] = key;
                continue;
            }
            //这里模拟hash冲突，形成链表的过程
            tab[index] = tab[index] +"->"+ key;
        }
        System.out.println(JSON.toJSONString(tab));
    }

    /**
     * 测试扰动函数，可以明显的发现，增加扰动函数之后，碰撞概率变低了
     */
    @Test
    public void test4(){
        String a = "张三";
        String b = "李四";
        String c = "王五";

        //未添加扰动函数
        System.out.println(a.hashCode() & 15);
        System.out.println(b.hashCode() & 15);
        System.out.println(c.hashCode() & 15);

        System.out.println("----------");

        //增加扰动函数
        System.out.println(hash(a) & 15);
        System.out.println(hash(b)& 15);
        System.out.println(hash(c)& 15);

    }

    //确定数组下标
    public int indexFor(int h, int length){
        return h & (length-1);
    }
    //扰动函数
    public int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    @Test
    public void test5() {
        String a = "vfbh";
        String b = "zuio";
        int hash = hash(b);
        int oldCap = 16;
        int newCap = 32;
        //老位置数组下标
        int oldIndex = indexFor(hash, oldCap);
        //新位置数组下标
        int newIndex = indexFor(hash, newCap);
        System.out.println(hash);
        System.out.println("老位置数组下标"+oldIndex);
        System.out.println("新位置数组下标"+newIndex);

        if ((hash & oldCap) == 0) {
            System.out.println("数组下标不变");
        } else {
            System.out.println("新位置数组下标(不重新计算hash)" + (oldIndex + oldCap));
        }
    }

    @Test
    public void test6(){
        int binCount = 0;
        for(; ; ++binCount) {
            if (binCount==1){
                break;
            }
        }
        System.out.println(binCount);
//        ++binCount;
//        System.out.println(binCount++);
//        System.out.println(binCount);
    }
}
